#include "videodecode.h"
#include <QTime>
#include <QDebug>
#include <QStringList>
#include <chrono>

/*********************************** FFmpeg获取GPU硬件解码帧格式的回调函数 *****************************************/
static enum AVPixelFormat g_pixelFormat;

/**
 * @brief      回调函数，获取GPU硬件解码帧的格式
 * @param s
 * @param fmt
 * @return
 */
AVPixelFormat get_hw_format(AVCodecContext* s, const enum AVPixelFormat* fmt)
{
    Q_UNUSED(s)
    const enum AVPixelFormat* p;

    for (p = fmt; *p != -1; p++)
    {
        if(*p == g_pixelFormat)
        {
            return *p;
        }
    }

    qDebug() << "无法获取硬件表面格式.";         // 当同时打开太多路视频时，如果超过了GPU的能力，可能会返回找不到解码帧格式
    return AV_PIX_FMT_NONE;
}
/************************************************ END ******************************************************/

VideoDecode::VideoDecode()
{

}

VideoDecode::~VideoDecode()
{
}

void VideoDecode::globalInit()
{
    //        av_register_all();         // 已经从源码中删除
    /**
     * 初始化网络库,用于打开网络流媒体，此函数仅用于解决旧GnuTLS或OpenSSL库的线程安全问题。
     * 一旦删除对旧GnuTLS和OpenSSL库的支持，此函数将被弃用，并且此函数不再有任何用途。
     */
    avformat_network_init();
}

void VideoDecode::globalUnInit()
{
    avformat_network_deinit();
}

qreal VideoDecode::rationalToDouble(AVRational* rational)
{
    qreal frameRate = (rational->den == 0) ? 0 : (qreal(rational->num) / rational->den);
    return frameRate;
}

void VideoDecode::setStreamDecodeCallback(StreamDecodeCallback funStreamDecodeCallback, AudioStreamDecodeCallback funAudioStreamDecodeCallback, void * userData)
{
    funCallbackByStreamDecode = funStreamDecodeCallback;
    funCallbackByAudioStreamDecode = funAudioStreamDecodeCallback;
    userDataByStreamDecode = userData;
}
void VideoDecode::setFileStatusCallback(FileStatusCallback funFileStatusCallback, void * userData)
{
    funCallbackByFileStatus = funFileStatusCallback;
    userDataByFileStatus = userData;
}

//初始化硬件解码器
void VideoDecode::initHWDecoder(const AVCodec *codec)
{
    if(!codec) return;

    for(int i = 0; ; i++)
    {
        const AVCodecHWConfig* config = avcodec_get_hw_config(codec, i);    // 检索编解码器支持的硬件配置。
        if(!config)
        {
            qDebug() << "打开硬件解码器失败！";
            return;          // 没有找到支持的硬件配置
        }

        if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)       // 判断是否是设备类型
        {
            for(auto i : vecHWDeviceTypes)
            {
                if(config->device_type == AVHWDeviceType(i))                 // 判断设备类型是否是支持的硬件解码器
                {
                    g_pixelFormat = config->pix_fmt;

                    // 打开指定类型的设备，并为其创建AVHWDeviceContext。
                    int ret = av_hwdevice_ctx_create(&hw_device_ctx, config->device_type, nullptr, nullptr, 0);
                    if(ret < 0)
                    {
                        freeDecode();
                        return ;
                    }
                    qDebug() << "打开硬件解码器：" << av_hwdevice_get_type_name(config->device_type);
                    codecCtx->hw_device_ctx = av_buffer_ref(hw_device_ctx);  // 创建一个对AVBuffer的新引用。
                    codecCtx->get_format = get_hw_format;                    // 由一些解码器调用，以选择将用于输出帧的像素格式
                    return;
                }
            }
        }
    }
}

//硬件解码完成需要将数据从GPU复制到CPU
bool VideoDecode::dataCopy()
{
    if(frame->format != g_pixelFormat)
    {
        av_frame_unref(frame);
        return false;
    }

    // av_hwframe_map处理速度比av_hwframe_transfer_data快（av_hwframe_map在ffmpeg3.3以后才有）
    int ret = av_hwframe_map(frameHW, frame, AV_HWFRAME_MAP_READ);                   // 映射硬件数据帧
    /*
     av_hwframe_map 映射硬件数据帧，第3个参数值有三种类型：
     AV_HWFRAME_MAP_READ：目标帧可读。
     AV_HWFRAME_MAP_WRITE：目标帧可写。
     AV_HWFRAME_MAP_DIRECT：避免数据拷贝（依赖硬件支持）‌。
     优先使用 AV_HWFRAME_MAP_DIRECT 减少内存拷贝开销‌。
     使用AV_HWFRAME_MAP_DIRECT时，你应该确保你的应用逻辑不会修改通过映射获得的软件帧内容，以避免不期望的副作用。
     使用AV_HWFRAME_MAP_READ时，你将获得数据的一致性但可能会有性能上的损失。
     */
    if(ret >= 0)
    {
        //映射硬件数据帧成功
        frameHW->width = frame->width;
        frameHW->height = frame->height;
    }
    else
    {
        //映射硬件数据帧失败
        ret = av_hwframe_transfer_data(frameHW, frame, 0);       // 将解码后的数据从GPU复制到CPU(frameHW) 比较耗时，但硬解码速度比软解码快很多
        if(ret < 0)
        {
          av_frame_unref(frame);
          return false;
        }
        av_frame_copy_props(frameHW, frame);   // 仅将“metadata”字段从src复制到dst。
    }

    return true;
}

void VideoDecode::setHWDecoder(bool flag)
{
    hwDecoderFlag = flag;
}
bool VideoDecode::isHWDecoder()
{
    return hwDecoderFlag;
}

bool VideoDecode::open(const QString& url)
{
    if(url.isNull()) return false;

    AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;      // ffmpeg支持的硬件解码器
    QStringList strTypes;
    while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)       // 遍历支持的设备类型。
    {
        vecHWDeviceTypes.push_back(type);
        const char* ctype = av_hwdevice_get_type_name(type);  // 获取AVHWDeviceType的字符串名称。
        if(ctype)
        {
            strTypes.append(QString(ctype));
        }
    }
    qDebug() << "支持的硬件解码器:";
    qDebug() << strTypes;

      AVDictionary* dict = nullptr;
      av_dict_set(&dict, "rtsp_transport", "tcp", 0);      // 设置rtsp流使用tcp打开，如果打开失败错误信息为【Error number -135 occurred】可以切换（UDP、tcp、udp_multicast、http），比如vlc推流就需要使用udp打开
      av_dict_set(&dict, "max_delay", "3", 0);             // 设置最大复用或解复用延迟（以微秒为单位）。当通过【UDP】 接收数据时，解复用器尝试重新排序接收到的数据包（因为它们可能无序到达，或者数据包可能完全丢失）。这可以通过将最大解复用延迟设置为零（通过max_delayAVFormatContext 字段）来禁用。
      av_dict_set(&dict, "timeout", "1000000", 0);         // 以微秒为单位设置套接字 TCP I/O 超时，如果等待时间过短，也可能会还没连接就返回了。

      // 打开输入流并返回解封装上下文
      int ret = avformat_open_input(&formatCtx,          // 返回解封装上下文
                                    url.toStdString().data(),  // 打开视频地址
                                    nullptr,                   // 如果非null，此参数强制使用特定的输入格式。自动选择解封装器（文件格式）
                                    &dict);                    // 参数设置
      // 释放参数字典
      if(dict)
      {
          av_dict_free(&dict);
      }
      // 打开视频失败
      if(ret < 0)
      {
          qDebug() << "Failed to avformat_open_input";
          return false;
      }

      // 读取媒体文件的数据包以获取流信息。
      ret = avformat_find_stream_info(formatCtx, nullptr);
      if(ret < 0)
      {
          qDebug() << "Failed to avformat_find_stream_info";
          freeDecode();
          return false;
      }
      totalTime = formatCtx->duration / (AV_TIME_BASE / 1000); // 计算视频总时长（毫秒）
      qDebug() << QString("视频总时长：%1 ms，[%2]").arg(totalTime).arg(QTime::fromMSecsSinceStartOfDay(int(totalTime)).toString("HH:mm:ss zzz"));

      audioStreamIndex = av_find_best_stream(formatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
      if(audioStreamIndex < 0)
      {
          // 错误处理：遍历所有流查找音频流
           for (int i = 0; i < formatCtx->nb_streams; i++)
           {
               if (formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                   audioStreamIndex = i;
                   break;
               }
           }
      }

      // 通过AVMediaType枚举查询视频流ID（也可以通过遍历查找），最后一个参数无用
      videoStreamIndex = av_find_best_stream(formatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
      if(videoStreamIndex < 0)
      {
          qDebug() << "Failed to av_find_best_stream";
          freeDecode();
          return false;
      }

      AVStream* videoStream = formatCtx->streams[videoStreamIndex];  // 通过查询到的索引获取视频流

      // 获取视频图像分辨率（AVStream中的AVCodecContext在新版本中弃用，改为使用AVCodecParameters）
      width = videoStream->codecpar->width;
      height = videoStream->codecpar->height;
      frameRate = rationalToDouble(&videoStream->avg_frame_rate);  // 视频帧率

      // 通过解码器ID获取视频解码器（新版本返回值必须使用const）
      const AVCodec* codec = avcodec_find_decoder(videoStream->codecpar->codec_id);
      totalFrames = videoStream->nb_frames;
      qDebug() << QString("分辨率：[w:%1,h:%2] 帧率：%3  总帧数：%4  解码器：%5")
                  .arg(width).arg(height).arg(frameRate).arg(totalFrames).arg(codec->name);

      // 分配AVCodecContext并将其字段设置为默认值。
      codecCtx = avcodec_alloc_context3(codec);
      if(!codecCtx)
      {
          qDebug() << "Failed to avcodec_alloc_context3 video";
          freeDecode();
          return false;
      }

      /*
      // 设置输入流的颜色参数
      codecCtx->color_primaries = AVCOL_PRI_BT470BG; // BT.601对应的原色
      codecCtx->color_trc = AVCOL_TRC_SMPTE170M;     // BT.601传输特性
      codecCtx->colorspace = AVCOL_SPC_BT470BG;      // 转换矩阵标识
      */

      // 使用视频流的codecpar为解码器上下文赋值
      ret = avcodec_parameters_to_context(codecCtx, videoStream->codecpar);
      if(ret < 0)
       {
          qDebug() << "Failed to avcodec_parameters_to_context";
          freeDecode();
          return false;
       }

       codecCtx->flags2 |= AV_CODEC_FLAG2_FAST;    // 允许不符合规范的加速技巧。
       codecCtx->thread_count = 8;                 // 使用8线程解码

       if(isHWDecoder())
       {
           initHWDecoder(codec);     // 初始化硬件解码器（在avcodec_open2前调用）
       }

      // 初始化解码器上下文，如果之前avcodec_alloc_context3传入了解码器，这里设置NULL就可以
      ret = avcodec_open2(codecCtx, nullptr, nullptr);
      if(ret < 0)
      {
          qDebug() << "Failed to avcodec_open2 video";
          freeDecode();
          return false;
      }

      //音频
      if(audioStreamIndex >= 0)
      {
          AVStream* audioStream = formatCtx->streams[audioStreamIndex];
          const AVCodec* codec_audio = avcodec_find_decoder(audioStream->codecpar->codec_id);

          codecCtx_Audio = avcodec_alloc_context3(codec_audio);
          if(!codecCtx_Audio)
          {
              qDebug() << "Failed to avcodec_alloc_context3 audio";
              freeDecode();
              return false;
          }

          ret = avcodec_parameters_to_context(codecCtx_Audio, audioStream->codecpar);
          if(ret < 0)
           {
              qDebug() << "Failed to avcodec_parameters_to_context audio";
              freeDecode();
              return false;
           }

          codecCtx_Audio->flags2 |= AV_CODEC_FLAG2_FAST;    // 允许不符合规范的加速技巧。
          codecCtx_Audio->thread_count = 8;                 //

          ret = avcodec_open2(codecCtx_Audio, nullptr, nullptr);
          if(ret < 0)
          {
              qDebug() << "Failed to avcodec_open2 audio";
              freeDecode();
              return false;
          }
      }

      // 分配AVPacket并将其字段设置为默认值。
      packet = av_packet_alloc();
      if(!packet)
      {
          qDebug() << "Failed to av_packet_alloc";
          freeDecode();
          return false;
      }

      // 初始化帧和转换上下文
      frame = av_frame_alloc();
      rgbFrame = av_frame_alloc();
      frameHW = av_frame_alloc();
      frame_audio = av_frame_alloc();
      int size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codecCtx->width, codecCtx->height, 1);
      buffer = (uint8_t *)av_malloc(size + 1000);
      av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, buffer, AV_PIX_FMT_RGB24,
                           codecCtx->width, codecCtx->height, 1);

      /*
      // 初始化 SWS 上下文（YUV -> RGB 转换）
      swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt,
                              codecCtx->width, codecCtx->height, AV_PIX_FMT_RGB24,
                              SWS_BILINEAR, nullptr, nullptr, nullptr);
     */
    stopWorkFlag = false;
    std::thread t(std::bind(&VideoDecode::decodeProccessThread,this));
    threadDecode = std::move(t);

    return true;
}

void VideoDecode::close()
{
    stopWorkFlag = true;
    pauseWorkFlag = false;

    // 因为avformat_flush不会刷新AVIOContext (s->pb)。如果有必要，在调用此函数之前调用avio_flush(s->pb)。
    if(formatCtx && formatCtx->pb)
    {
        avio_flush(formatCtx->pb);
    }
    if(formatCtx)
    {
        avformat_flush(formatCtx);   // 清理读取缓冲
    }

    if(threadDecode.joinable())
    {
        threadDecode.join();
    }

    freeDecode();
}

bool VideoDecode::isClose()
{
    return stopWorkFlag;
}

void VideoDecode::setPause(bool pause)
{
    pauseWorkFlag = pause;
}
bool VideoDecode::isPause()
{
    return pauseWorkFlag;
}

QImage VideoDecode::ConvertRGB24FrameToQImage(unsigned char *data, int width, int height)
{
    // 创建 QImage 并显示
    QImage img(data, width, height, QImage::Format_RGB888);
    return img;
}

void VideoDecode::decodeProccessThread()
{
  std::chrono::high_resolution_clock::time_point tpStart = std::chrono::high_resolution_clock::now();
  int nWaitTimes = 40;
  if(frameRate != 0)
  {
     nWaitTimes = 1000.0/frameRate;
  }

  long long llDecodeTs = 0;
  long long llPlayTs = 0;
  long long llDecodeTs_Audio = 0;
  long long llPlayTs_Audio = 0;
  long long llStartPlayTs = 0;
  bool bStartPlayTsSetValueFlag = false;
  bool bProccessFileTail = false;

    while (true)
    {
        if(stopWorkFlag)
        {
            break;
        }

        if(pauseWorkFlag)
        {
            std::this_thread::sleep_for(std::chrono::microseconds(200000));
            bStartPlayTsSetValueFlag = false;
            tpStart = std::chrono::high_resolution_clock::now();
            llDecodeTs = 0;
            llPlayTs = 0;
            llStartPlayTs = 0;
            continue;
        }

        // 读取下一帧数据
        int readRet = av_read_frame(formatCtx, packet);
        if(readRet < 0)
        {
            if (readRet == AVERROR_EOF)
            {
               int ret = -1;
               if(packet->stream_index == videoStreamIndex)
               {
                   ret = avcodec_send_packet(codecCtx, packet); // 读取完成后向解码器中传如空AVPacket，否则无法读取出最后几帧
               }
               else if(packet->stream_index == audioStreamIndex)
               {
                   ret = avcodec_send_packet(codecCtx_Audio, packet);
               }
               av_packet_unref(packet);
               bProccessFileTail = true;
               break;
            }
            else
            {
                break;
            }
        }
        else
        {
            if(stopWorkFlag)
            {
                break;
            }

            if(packet->stream_index == videoStreamIndex)     // 如果是图像数据则进行解码
            {
                av_packet_rescale_ts(packet, formatCtx->streams[videoStreamIndex]->time_base, codecCtx->time_base); // 转换至解码器时间基‌
                // 将读取到的原始数据包传入解码器
                int ret = avcodec_send_packet(codecCtx, packet);
                if(ret < 0)
                {
                    qDebug() << "Error sending packet video";
                    av_packet_unref(packet);
                    continue;
                }


                // 接收解码后的帧(这里一次只解码一帧)
               ret = avcodec_receive_frame(codecCtx, frame);
                if (ret == AVERROR(EAGAIN))
                {
                    av_packet_unref(packet);
                    continue;
                }
                else if (ret == AVERROR_EOF)
                {
                    av_packet_unref(packet);

                    //当无法读取到AVPacket并且解码器中也没有数据时表示读取完成
                    bProccessFileTail = true;
                    break;
                }
                else if (ret < 0)
                {
                    qDebug() << "Error during decoding";
                    av_packet_unref(packet);
                    continue;
                }
                else
                {
                    // 这样写是为了兼容软解码或者硬件解码打开失败情况
                     AVFrame*  frameTemp = frame;
                     if(!frame->data[0])               // 如果是硬件解码就进入
                      {
                           // 将解码后的数据从GPU拷贝到CPU
                           if(!dataCopy())
                           {
                                av_frame_unref(frameHW);
                                continue;
                           }

                           frameTemp = frameHW;
                     }

                    // 处理时间戳的核心逻辑
                     int64_t raw_pts = frameTemp->pts;
                     int64_t raw_dts = frameTemp->pkt_dts;
                     // 处理未定义时间戳的情况
                     if (raw_pts == AV_NOPTS_VALUE)
                     {
                         // 使用DTS或估算PTS（需要根据帧率等参数）
                         if(raw_dts != AV_NOPTS_VALUE)
                         {
                             raw_pts = raw_dts;
                         }
                         else
                         {
                             raw_pts = 0;
                             raw_dts = 0;
                         }
                     }

                     // 转换为显示时间戳（秒）
                     double display_time = raw_pts * av_q2d(codecCtx->time_base);

                     // 转换为全局时间基（例如用于音视频同步）
                     AVRational timeBaseTemp{1, AV_TIME_BASE};//AV_TIME_BASE_Q
                     llPlayTs = av_rescale_q(raw_pts, codecCtx->time_base, timeBaseTemp);
                     llDecodeTs = av_rescale_q(raw_dts, codecCtx->time_base, timeBaseTemp);
                     if(!bStartPlayTsSetValueFlag)
                     {
                         llStartPlayTs = llPlayTs;
                         bStartPlayTsSetValueFlag = true;
                     }

                     qDebug("Video Frame:%4d PTS:%lld display_time:%.2f DTS:%lld llPlayTs:%lld llDecodeTs:%lld packet dts:%lld pts:%lld",
                                   codecCtx->frame_number, raw_pts, display_time, raw_dts, llPlayTs, llDecodeTs, packet->dts, packet->pts);


                     av_packet_unref(packet);  // 释放数据包，引用计数-1，为0时释放空间

                     if(!swsCtx || (frameTemp->width != width || frameTemp->height != height))
                     {
                         //重新申请
                         width = frameTemp->width;
                         height = frameTemp->height;
                         if(swsCtx)
                         {
                             sws_freeContext(swsCtx);
                             swsCtx = nullptr;
                         }

                         if(buffer)
                         {
                             av_free(buffer);
                             buffer = nullptr;
                         }
                         int size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, frameTemp->width, frameTemp->height, 1);
                         buffer = (uint8_t *)av_malloc(size + 1000);
                         av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, buffer, AV_PIX_FMT_RGB24,
                                              frameTemp->width, frameTemp->height, 1);

                         swsCtx = sws_getCachedContext(swsCtx,
                                                               frameTemp->width,                     // 输入图像的宽度
                                                               frameTemp->height,                    // 输入图像的高度
                                                               (AVPixelFormat)frameTemp->format,     // 输入图像的像素格式
                                                               frameTemp->width,                     // 输出图像的宽度
                                                               frameTemp->height,                    // 输出图像的高度
                                                               AV_PIX_FMT_RGB24,                    // 输出图像的像素格式
                                                               SWS_BILINEAR,                       // 选择缩放算法(只有当输入输出图像大小不同时有效),一般选择SWS_FAST_BILINEAR
                                                               nullptr,                            // 输入图像的滤波器信息, 若不需要传NULL
                                                               nullptr,                            // 输出图像的滤波器信息, 若不需要传NULL
                                                               nullptr);
                     }

                     //休眠等待
                     long long llPlayTsDiff = llPlayTs - llStartPlayTs;
                     auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - tpStart);
                     // 计算需要等待的时间（单位：微秒）
                     int64_t delay = llPlayTsDiff - duration.count();
                     // 同步控制
                      if (delay > 0)
                      {
                         std::this_thread::sleep_for(std::chrono::microseconds(delay)); // 等待至目标时间‌
                      }
                      else if (delay < -3000000)
                      {
                         // 允许3000ms误差阈值
                         // 丢弃滞后帧，追赶进度‌
                         av_frame_unref(frame);
                         av_frame_unref(frameHW);
                         continue;
                      }
                      /*
                      else if (delay < -100000)
                      {
                         // 允许100ms误差阈值
                         // 丢弃滞后帧，追赶进度‌
                         av_frame_unref(frame);
                         av_frame_unref(frameHW);
                         continue;
                      }
                      */

                      if(frameTemp->format == AV_PIX_FMT_YUV420P)
                      {
                          //回调流数据（方便渲染）
                          if(funCallbackByStreamDecode && !stopWorkFlag)
                          {
                              funCallbackByStreamDecode(StreamType_Video,FormatType_YUV420P,llDecodeTs,llPlayTs,frameTemp->width,frameTemp->height,frameTemp->data, frameTemp->linesize, userDataByStreamDecode);
                          }
                      }
                      else if(frameTemp->format == AV_PIX_FMT_NV12)
                      {
                          //回调流数据（方便渲染）
                          if(funCallbackByStreamDecode && !stopWorkFlag)
                          {
                              funCallbackByStreamDecode(StreamType_Video,FormatType_NV12,llDecodeTs,llPlayTs,frameTemp->width,frameTemp->height,frameTemp->data, frameTemp->linesize, userDataByStreamDecode);
                          }
                      }
                      else
                      {
                          //其他格式，转换成rgb
                          // 转换颜色空间到 RGB24
                          sws_scale(swsCtx, frameTemp->data, frameTemp->linesize, 0, frameTemp->height, rgbFrame->data, rgbFrame->linesize);
                          //回调流数据（方便渲染）
                          if(funCallbackByStreamDecode && !stopWorkFlag)
                          {
                              funCallbackByStreamDecode(StreamType_Video,FormatType_RGB24,llDecodeTs,llPlayTs,frameTemp->width,frameTemp->height,rgbFrame->data, rgbFrame->linesize, userDataByStreamDecode);
                          }
                      }

                      av_frame_unref(frame);
                      av_frame_unref(frameHW);
                }
            }
            else if(packet->stream_index == audioStreamIndex) //音频流
            {
                av_packet_rescale_ts(packet, formatCtx->streams[audioStreamIndex]->time_base, codecCtx_Audio->time_base); // 转换至解码器时间基‌
                // 将读取到的原始数据包传入解码器
                int ret = avcodec_send_packet(codecCtx_Audio, packet);
                if(ret < 0)
                {
                    qDebug() << "Error sending packet audio";
                    av_packet_unref(packet);
                    continue;
                }


                // 接收解码后的帧(这里一次只解码一帧)
                ret = avcodec_receive_frame(codecCtx_Audio, frame_audio);
                if (ret == AVERROR(EAGAIN))
                {
                    av_packet_unref(packet);
                    continue;
                }
                else if (ret == AVERROR_EOF)
                {
                    av_packet_unref(packet);

                    //当无法读取到AVPacket并且解码器中也没有数据时表示读取完成
                    bProccessFileTail = true;
                    break;
                }
                else if (ret < 0)
                {
                    qDebug() << "Error during decoding";
                    av_packet_unref(packet);
                    continue;
                }
                else
                {
                    // 这样写是为了兼容软解码或者硬件解码打开失败情况
                     AVFrame*  frameTemp = frame_audio;
                    // 处理时间戳的核心逻辑
                     int64_t raw_pts = frameTemp->pts;
                     int64_t raw_dts = frameTemp->pkt_dts;
                     // 处理未定义时间戳的情况
                     if (raw_pts == AV_NOPTS_VALUE)
                     {
                         // 使用DTS或估算PTS（需要根据帧率等参数）
                         if(raw_dts != AV_NOPTS_VALUE)
                         {
                             raw_pts = raw_dts;
                         }
                         else
                         {
                             raw_pts = 0;
                             raw_dts = 0;
                         }
                     }

                     // 转换为显示时间戳（秒）
                     double display_time = raw_pts * av_q2d(codecCtx_Audio->time_base);

                     // 转换为全局时间基（例如用于音视频同步）
                     AVRational timeBaseTemp{1, AV_TIME_BASE};//AV_TIME_BASE_Q
                     llPlayTs_Audio = av_rescale_q(raw_pts, codecCtx_Audio->time_base, timeBaseTemp);
                     llDecodeTs_Audio = av_rescale_q(raw_dts, codecCtx_Audio->time_base, timeBaseTemp);
                     if(!bStartPlayTsSetValueFlag)
                     {
                         llStartPlayTs = llPlayTs_Audio;
                         bStartPlayTsSetValueFlag = true;
                     }

                     qDebug("Audio Frame:%4d PTS:%lld display_time:%.2f DTS:%lld llPlayTs:%lld llDecodeTs:%lld packet dts:%lld pts:%lld",
                                   codecCtx_Audio->frame_number, raw_pts, display_time, raw_dts, llPlayTs_Audio, llDecodeTs_Audio, packet->dts, packet->pts);

                     if(!swrCtxAudo)
                     {
                         //初始化重采样器（转为 S16 立体声，PortAudio 兼容）
                         swrCtxAudo = swr_alloc_set_opts(
                                          NULL,
                                          AV_CH_LAYOUT_STEREO,           // 输出声道布局
                                          AV_SAMPLE_FMT_S16,             // 输出采样格式（PortAudio 常用）
                                          frame_audio->sample_rate,            // 输出采样率
                                          formatCtx->streams[audioStreamIndex]->codecpar->channel_layout,         // 输入声道布局
                                          (AVSampleFormat)formatCtx->streams[audioStreamIndex]->codecpar->format,                 // 输入采样格式
                                          formatCtx->streams[audioStreamIndex]->codecpar->sample_rate,            // 输入采样率
                                          0, NULL
                                      );
                         swr_init(swrCtxAudo);

                         /*
                         av_samples_alloc((uint8_t**)&bufferAudio, NULL, codecCtx_Audio->channels,
                                                  frame_audio->nb_samples, AV_SAMPLE_FMT_S16, 0);
                         */

                         bufferAudioSize = av_samples_get_buffer_size(
                                            NULL, codecCtx_Audio->channels, frame_audio->nb_samples,
                                            AV_SAMPLE_FMT_S16, 0);
                         bufferAudio = (uint8_t *)av_malloc(bufferAudioSize);              
                     }
                     swr_convert(swrCtxAudo, (uint8_t**)&bufferAudio, frame_audio->nb_samples,
                                      (const uint8_t**)frame_audio->data, frame_audio->nb_samples);

                     av_packet_unref(packet);  // 释放数据包，引用计数-1，为0时释放空间


                     //休眠等待
                     long long llPlayTsDiff = llPlayTs_Audio - llStartPlayTs;
                     auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - tpStart);
                     // 计算需要等待的时间（单位：微秒）
                     int64_t delay = llPlayTsDiff - duration.count();
                     // 同步控制
                      if (delay > 0)
                      {
                         //std::this_thread::sleep_for(std::chrono::microseconds(delay)); // 等待至目标时间‌
                      }
                      else if (delay < -100000)
                      {
                         // 允许100ms误差阈值
                         // 丢弃滞后帧，追赶进度‌
                         av_frame_unref(frame_audio);
                         continue;
                      }

                      if(formatCtx->streams[audioStreamIndex]->codecpar->codec_id == AV_CODEC_ID_AAC)
                      {
                          //回调流数据（方便渲染）
                          if(funCallbackByAudioStreamDecode && !stopWorkFlag)
                          {
                              funCallbackByAudioStreamDecode(frame_audio->sample_rate, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, AV_CH_LAYOUT_STEREO, (unsigned char *)bufferAudio, frame_audio->nb_samples, userDataByStreamDecode);
                          }
                      }

                      av_frame_unref(frame_audio);
                }
            }
            else
            {
                //其他流（比如：音频）
                av_packet_unref(packet);
                continue;
            }
        }
    }

    if(bProccessFileTail && !stopWorkFlag)
    {
        if(funCallbackByFileStatus != nullptr)
        {
            funCallbackByFileStatus(FileStatus_OverFileTail, 0, userDataByFileStatus);
        }
    }

    qDebug()<<"thread is eixt";
}

void VideoDecode::freeDecode()
{
    // 释放资源
   if (swsCtx)
   {
       sws_freeContext(swsCtx);
       swsCtx = nullptr;
   }

   if(swrCtxAudo)
   {
       swr_free(&swrCtxAudo);
       swrCtxAudo = nullptr;
   }

  if (rgbFrame)
  {
      av_frame_free(&rgbFrame);
      rgbFrame = nullptr;
  }

  if (frame)
  {
      av_frame_free(&frame);
      frame = nullptr;
  }

  if(frameHW)
  {
      av_frame_free(&frameHW);
      frameHW = nullptr;
  }

  if(frame_audio)
  {
      av_frame_free(&frame_audio);
      frame_audio = nullptr;
  }

  if (codecCtx)
  {
      avcodec_free_context(&codecCtx);
      codecCtx = nullptr;
  }

  if(codecCtx_Audio)
  {
      avcodec_free_context(&codecCtx_Audio);
      codecCtx_Audio = nullptr;
  }

  if (formatCtx)
  {
      avformat_close_input(&formatCtx);
      formatCtx = nullptr;
  }

  if(buffer != nullptr)
  {
      av_free(buffer);
      buffer = nullptr;
  }
}
